/*
 * GPL License jazz, goog_pam is (c)Rich Lundeen
 *
 * This file is a wrapper to call the network connection stuff
 * from the password module
 *
 * This seems to be necessary because we need the google admin to be able to 
 * programatically change the password using the google apis (there currently
 * is no option to authenticate as a user and change the password that way).
 * Because of this, the python program needs the provisioning api - and so 
 * needs the google admin's password - which means we need to temporarily escalate
 * privs. The install script setuids this to a new goog_pam user, which has
 * access to this information.
 *
 * All user authentication essentiallly needs to be here
 *
 * As it is written, any user can change the password of a google apps account
 * of the same name. 
 * TODO make it possible to override this in a configfile - keep in mind anyone can
 * call this script with whatever args they want
 *
 */

#include <stdio.h>
#include <string.h>
#include <pwd.h>
#include <syslog.h>
#include <stdlib.h>
#include <sys/wait.h>

//there's no reason a username + password should be longer than this
#define TOOLONG 1024

//this program is setuid as goog_pam, be cautious
int main(int argc, char* argv[]) {
  
  char* username = argv[1];
  char* password = argv[2];

  int user_user_id = getuid();
  int pam_user_id  = geteuid();
 
  char* realusername = getpwuid(user_user_id)->pw_name;
  char* netconnect = "/etc/security/goog_pam/goog_pass_sock";  
  char* sysbuf;

  int rc;

  char* progarg0 = "goog_pass_sock";
  int execreturn;
  pid_t PID;

  //verify user
  //TODO optional token - get from config file.
  if (strcmp(realusername, username) && (user_user_id != 0))  {
    //username error - most likely the script has not been called from pam
    //report an error here to see possibilities about what's going on
    syslog(LOG_ERR, "pam_google pass: access error, user %s ran as %s", realusername, username);
    return(-5);
  }

  //as a precaution, check the length, nothing bad should theoretically happen if this didn't exist
  //but this way testing is iteratable
  if ((strlen(username) + strlen(password)) > TOOLONG) {
    return(-7);
  }

  PID = fork();
  if (PID == 0) {
    //child
    char* argvarray[4] = {progarg0, username, password, (char *) 0};
    execv(netconnect, argvarray);
    return -1;
  }
  else if (PID < 0) {
    return -1;
  }

  wait(&execreturn);
  //make sure this does exit properly and isn't killed
  if (WIFEXITED(execreturn)) {
    rc = WEXITSTATUS(execreturn);
  }
  else {
    //1 is the errorcode for fork
    return 1;
  }


  //return what the python prog tells us to
  return (rc);
}  
